package com.movie.ticket.sale.ticketassembly.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.movie.ticket.sale.moviecommon.common.Result;
import com.movie.ticket.sale.moviecommon.model.TOrderMovie;
import com.movie.ticket.sale.provide.MessageUtil;
import com.movie.ticket.sale.provide.MovieTicket;
import com.movie.ticket.sale.ticketassembly.alipay.AlipayBean;
import com.movie.ticket.sale.ticketassembly.alipay.AlipayRefund;
import com.movie.ticket.sale.ticketassembly.alipay.AlipayUtil;
import com.movie.ticket.sale.ticketassembly.alipay.PropertiesConfig;
import com.movie.ticket.sale.ticketassembly.alipay.RefundBean;
import com.movie.ticket.sale.ticketassembly.component.HttpUtil;
import com.movie.ticket.sale.ticketassembly.dao.TOrderAnnualMapper;
import com.movie.ticket.sale.ticketassembly.dao.TOrderMovieMapper;
import com.movie.ticket.sale.ticketassembly.dao.TOrderTicketMapper;
import com.movie.ticket.sale.ticketassembly.dao.TOrderVipMapper;
import com.movie.ticket.sale.ticketassembly.service.ITCinemaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author： Micsal
 * @create-time： 2020.12.09 16:24
 * @version： 1.0
 * @description： desc
 */
@RestController
@Slf4j
@RefreshScope
public class Ticket implements MessageUtil, MovieTicket {

    //配置文件中的数据
    @Value("${custom.telPattern}")
    private String telPattern;
    @Value("${custom.messageToken}")
    private String messageToken;
    @Value("${custom.tplId}")
    private String tplId;

    //注入组件
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private TOrderMovieMapper tOrderMovieMapper;
    @Autowired
    private TOrderTicketMapper tOrderTicketMapper;
    @Autowired
    private TOrderVipMapper tOrderVipMapper;
    @Autowired
    private TOrderAnnualMapper tOrderAnnualMapper;

    @Autowired
    private ITCinemaService cinemaService;

    @Override
    public Result sendMessage(String tel, String message) {
        log.info("发送短信:{},{}", tel, message);

        if (tel == null || message == null || "".equals(tel) || "".equals(message))
            return Result.fail(426, "手机号或信息不能为空");

        if (!tel.matches(telPattern))
            return Result.fail(426, "手机号不合法");

        String host = "http://www.api51.cn";
        String path = "/api/smsApi/send";
        String method = "POST";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("mobile", tel);
        bodys.put("params", message);
        bodys.put("sign", "网极科技");
        bodys.put("token", messageToken);
        bodys.put("tpl_id", tplId);
        try {
            HttpResponse response = HttpUtil.doPost(host, path, method, headers, querys, bodys);
            if (response.getStatusLine().getStatusCode() != 200)
                return Result.fail(426, "短信服务器连接异常");

            HttpEntity entity = response.getEntity();
            if (null == entity)
                return Result.fail(426, "短信服务器响应body为空");

            //获取entity
            String s = EntityUtils.toString(entity, "UTF-8");

            //转换成jsonObj
            JSONObject obj = JSONObject.parseObject(s);

            int code = obj.getInteger("code");
            if (code == 1) {
                log.info("发送成功：{}，{}", tel, message);
                return Result.success();
            }
            String msg = obj.getString("msg");
            log.info("发送失败，{}", msg);
            return Result.fail(426, msg);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(426, e.getMessage());
        }
    }

    @Override
    public Result checkMessage(String tel, String code) {
        log.info("校验短信验证码:{},{}", tel, code);
        if (tel == null || code == null || "".equals(tel) || "".equals(code))
            return Result.fail(426, "手机号或信验证码不能为空");

        if (!tel.matches(telPattern))
            return Result.fail(426, "手机号不合法");

        String key = tel + ".MessageAuthenticationCode";
        BoundValueOperations<String, String> rs = redisTemplate.boundValueOps(key);
        String message = rs.get();
        if (null != message) {
            String oldCode = message.split("-")[0];
            if (oldCode.equals(code))
                return Result.success("验证成功");
            else
                return Result.fail(426, "验证码错误");
        } else {
            return Result.fail(426, "验证码已过期");
        }
    }

    @Override
    public Result orderTicketQuery(int currentPage, int pageSize, Map<String, Object> condition) {
        return null;
    }

    @Override
    public Result orderVipQuery(int currentPage, int pageSize, Map<String, Object> condition) {
        return null;
    }

    @Override
    public Result orderAnnualQuery(int currentPage, int pageSize, Map<String, Object> condition) {
        return null;
    }

    @Override
    public Result aliPay(String body, String tradeNo, String subject, double totalAmount) {
        log.info("支付请求处理:{}", tradeNo);
        String s = null;            //订单名称
        try {
            s = AlipayUtil.connect(new AlipayBean()
                    .setBody(body)                      //商品描述
                    .setOut_trade_no(tradeNo)      //商户订单号
                    .setTotal_amount(new StringBuffer().append(totalAmount))   //付款金额
                    .setSubject(subject));
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return Result.fail(426, e.getMessage());
        }
        log.info("请求后返回的字符串:{}", s);        //是一个前端页面
        return Result.success(s);
    }

    @Override
    public String aliPayNotifyUrl(String out_trade_no, String trade_no, String trade_status) {
        log.info("进入异步回调");

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        Map<String, String> params = getParamsMap(request);

        boolean signVerified = false;
        try {
            signVerified = AlipaySignature.rsaCheckV1(params, PropertiesConfig.getKey("alipay_public_key"), PropertiesConfig.getKey("charset"), PropertiesConfig.getKey("sign_type"));
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "失败：" + e.getMessage();
        }

        log.info("支付异步回调，验证签名 : {}", signVerified);
        if (!signVerified) {
            log.info("签名验证失败");
            return "签名验证失败";
        }

        trade_status = request.getParameter("trade_status");
        log.info("签名验证成功，获取支付状态：{}", trade_status);

        if (!trade_status.equals("TRADE_SUCCESS")) {
            log.info("支付失败");
            return "支付失败";
        }

        String otn = params.get("out_trade_no");
        String[] array = otn.split("_");

        int len = array.length;
        if (len != 4)
            return "非法订单号";
        String orderName = array[0];
        int id = Integer.parseInt(array[1]);
        log.info("订单id：{}",id);


        switch (orderName) {
            case "TOrderMovie":
                log.info("++用户购票订单：{}", otn);
                tOrderMovieMapper.payedChangeState(id);
                tOrderTicketMapper.payedChangeState(id);
                log.info("sql执行完毕");
                //获取用户手机号
                String userTel=array[3];
                String key="orderMessage_"+userTel;
                BoundHashOperations<String, String, String > rs = redisTemplate.boundHashOps(key);
                String checkCode=rs.get("checkCode");
                log.info("发送短信验证码：{}，{}",userTel,checkCode);
                log.info("发送结果：{}",sendMessage(userTel,"尊敬的用户在微票视界购票的入场码为"+checkCode).getData());
                break;
            case "TOrderVip":
                log.info("++用户vip订单：{}", otn);
                tOrderVipMapper.payedChangeState(id);
                log.info("sql执行完毕");
                break;
            case "TOrderAnnual":
                log.info("++影院年费订单：{}", otn);
                tOrderAnnualMapper.payedChangeState(id);
                log.info("sql执行完毕");
                break;
            default:
                log.info("++非法订单号：{}", otn);
                return "非法订单号";
        }

        return "支付成功";
    }

    @Override
    public String aliPayReturnUrl(String out_trade_no, String trade_no, String trade_status) {
        log.info("进入同步回调: {}", out_trade_no);

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        Map<String, String> params = getParamsMap(request);

        // 验证签名
        boolean signVerified = false;
        try {
            signVerified = AlipaySignature.rsaCheckV1(params, PropertiesConfig.getKey("alipay_public_key"), PropertiesConfig.getKey("charset"), PropertiesConfig.getKey("sign_type"));
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        log.info("同步回调，验证签名: {}", signVerified);
        if (signVerified) {
//            response.sendRedirect("/html/MenuManager.html");    //重定向
            return "支付成功！";
        } else {
            log.info("验证失败,不去更新状态");
            return "支付失败！";
        }
    }

    /**
     * 获取request中的参数
     */
    private Map<String, String> getParamsMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        return params;
    }

    public Result refund(String out_trade_no, double amount) {
        log.info("退款订单号:{}，退款金额:{}",out_trade_no,amount);
        Result re1 = AlipayRefund.connect(new RefundBean()
                .setRefund_amount(new StringBuffer().append(amount))
                .setOut_trade_no(out_trade_no));
        return re1;
    }

    @Override
    public Result addComment(MultipartFile[] files, double[] score, String comment) {
        return null;
    }

    @Override
    public Result queryComment(int currentPage, int pageSize, Map<String, Object> condition) {
        return null;
    }

    @Override
    public Result addComplain(MultipartFile[] files, double[] score, String comment) {
        return null;
    }

    @Override
    public Result queryComplain(int currentPage, int pageSize, Map<String, Object> condition) {
        return null;
    }

    @Override
    public Result addSet(String sets) {
        return null;
    }

    @Override
    public Result querySet(int peridId) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        String tel = request.getHeader("tel");
        String id = request.getHeader("id");
        String role = request.getHeader("role");

        String key = "manager." + role + "." + id;
        BoundValueOperations<String, String> rs = redisTemplate.boundValueOps(key);
        String value = rs.get();

        Map<String, Object> map = new HashMap<>();
        map.put("tel", tel);
        map.put("id", id);
        map.put("role", role);
        map.put("key", key);
        map.put("value", value);

        return Result.success(map);
    }
}
